package com.demo2.todo.service.impl;

import com.demo2.todo.exception.BadRequestException;
import com.demo2.todo.exception.ResourceNotFoundException;
import com.demo2.todo.model.dto.ReportProcessRequest;
import com.demo2.todo.model.dto.ReportRequest;
import com.demo2.todo.model.dto.ReportResponse;
import com.demo2.todo.model.entity.Report;
import com.demo2.todo.model.entity.Todo;
import com.demo2.todo.model.entity.User;
import com.demo2.todo.model.enums.ReviewStatus;
import com.demo2.todo.repository.ReportRepository;
import com.demo2.todo.repository.TodoRepository;
import com.demo2.todo.repository.ShareTodoRepository;
import com.demo2.todo.repository.UserRepository;
import com.demo2.todo.service.ReportService;
import com.demo2.todo.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author evi
 */
@Service
@RequiredArgsConstructor
public class ReportServiceImpl implements ReportService {
    private final ReportRepository reportRepository;
    private final TodoRepository todoRepository;
    private final ShareTodoRepository shareTodoRepository;
    private final UserService userService;
    private final UserRepository userRepository;

    @Override
    @Transactional
    public ReportResponse createReport(ReportRequest request, User reporter) {
        // 验证被举报的todo存在且是公开的
        Todo todo = todoRepository.findById(request.getTodoId())
                .orElseThrow(() -> new ResourceNotFoundException("Todo不存在"));

//        // 检查该todo是否公开分享
//        boolean isPublic = shareTodoRepository.existsByTodoIdAndIsPublicTrue(request.getTodoId());
//        if (!isPublic) {
//            throw new BadRequestException("只能举报公开分享的任务");
//        }

//        // 检查用户是否举报自己的todo
//        if (todo.getUserId().equals(reporter.getId())) {
//            throw new BadRequestException("不能举报自己的任务");
//        }

        Report report = new Report();
        report.setTodoId(request.getTodoId());
        report.setReporterId(reporter.getId());
        report.setReason(request.getReason());

        Report savedReport = reportRepository.save(report);
        return mapToDto(savedReport);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ReportResponse> getAllReports() {
        return reportRepository.findAllByOrderByCreatedAtDesc().stream()
                .map(this::mapToDto)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public ReportResponse processReport(Long reportId, ReportProcessRequest request, User admin) {
        Report report = reportRepository.findById(reportId)
                .orElseThrow(() -> new ResourceNotFoundException("举报不存在"));

        if (report.getStatus() != Report.ReportStatus.pending) {
            throw new BadRequestException("该举报已处理");
        }

        report.setStatus(Report.ReportStatus.valueOf(request.getStatus()));
        report.setProcessedAt(LocalDateTime.now());
        report.setProcessedBy(admin.getId());

        // 如果接受举报，将对应todo设为不公开
        if (request.getStatus().equals(Report.ReportStatus.ACCEPTED)) {
            shareTodoRepository.findByTodoId(report.getTodoId()).forEach(shareTodo -> {
                shareTodo.setPublic(false);
                shareTodoRepository.save(shareTodo);
            });
        }

        Report updatedReport = reportRepository.save(report);
        return mapToDto(updatedReport);
    }

    /**
     * 按状态查询举报
     * @param status 举报状态（null时返回所有）
     */
    @Override
    public List<ReportResponse> getReportsByStatus(Report.ReportStatus status) {
        List<Report> reports = (status == null)
                ? reportRepository.findAll()
                : reportRepository.findByStatusOrderByCreatedAtDesc(status);

        // 转换为Response
        return reports.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    @Transactional
    @Override
    public ReportResponse handleReport(Long reportId, Report.ReportStatus status, String comment) {
        // 1. 查找举报记录
        Report report = reportRepository.findById(reportId)
                .orElseThrow(() -> new ResourceNotFoundException("举报记录不存在: " + reportId));

        // 2. 更新举报状态
        report.setStatus(status);
        report.setProcessedAt(LocalDateTime.now());
        report.setProcessedBy(userService.getCurrentUserEntity().getId()); // 记录处理人
        reportRepository.save(report);

        // 3. 如果接受举报，处理对应的Todo（例如标记为违规）
        if (status == Report.ReportStatus.ACCEPTED) {
            Todo todo = todoRepository.findById(report.getTodoId())
                    .orElseThrow(() -> new ResourceNotFoundException("被举报的Todo不存在"));

            // 处理违规Todo（例如禁用分享、标记为违规）
            todo.setReviewStatus(ReviewStatus.rejected);
            todo.setShareToken(null); // 取消分享
            todo.setShareExpiresAt(null);
            todoRepository.save(todo);
        }

        return convertToResponse(report);
    }

    /**
     * 转换Report实体为Response
     */
    private ReportResponse convertToResponse(Report report) {
        ReportResponse response = new ReportResponse();
        response.setId(report.getId());
        response.setTodoId(report.getTodoId());
        response.setReporterId(report.getReporterId());
        response.setReason(report.getReason());
        response.setStatus(String.valueOf(report.getStatus()));
        response.setCreatedAt(report.getCreatedAt());
        response.setProcessedAt(report.getProcessedAt());

//        // 处理人信息
//        if (report.getProcessedBy() != null) {
//            userRepository.findById(report.getProcessedBy()).ifPresent(admin -> {
//                response.setProcessorUsername(admin.getUsername());
//            });
//        }
//        response.setReviewComment(report.getReviewComment());
        return response;
    }

    private ReportResponse mapToDto(Report report) {
        ReportResponse response = new ReportResponse();
        response.setId(report.getId());
        response.setTodoId(report.getTodoId());
        response.setReporterId(report.getReporterId());
        response.setReason(report.getReason());
        response.setStatus(report.getStatus().name());
        response.setCreatedAt(report.getCreatedAt());
        response.setProcessedAt(report.getProcessedAt());
        response.setProcessedBy(report.getProcessedBy());
        return response;
    }
}